package com.sztx.pay.center.rpc.component;

import java.util.Date;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.mortbay.log.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;

import com.alibaba.fastjson.JSONObject;
import com.sztx.pay.center.common.util.ConfigUtil;
import com.sztx.pay.center.common.util.Constance;
import com.sztx.pay.center.common.util.Constance.B2COrderState;
import com.sztx.pay.center.common.util.Constance.BindCardType;
import com.sztx.pay.center.common.util.Constance.CallBackOrderState;
import com.sztx.pay.center.common.util.Constance.CardActType;
import com.sztx.pay.center.common.util.Constance.CardType;
import com.sztx.pay.center.common.util.Constance.GuaranteeType;
import com.sztx.pay.center.common.util.Constance.IdCardType;
import com.sztx.pay.center.common.util.Constance.PayFlowState;
import com.sztx.pay.center.common.util.Constance.PayFlowType;
import com.sztx.pay.center.common.util.Constance.TradeMessageType;
import com.sztx.pay.center.common.util.Constance.TradeOrderType;
import com.sztx.pay.center.common.util.Constance.UserActType;
import com.sztx.pay.center.common.util.DateUtil;
import com.sztx.pay.center.common.util.JFUtils;
import com.sztx.pay.center.common.util.ValidateUtil;
import com.sztx.pay.center.common.yhbf.YHBFSensitiveEnc;
import com.sztx.pay.center.core.service.AccountService;
import com.sztx.pay.center.core.service.ActService;
import com.sztx.pay.center.core.service.BillnoService;
import com.sztx.pay.center.core.service.CallBackService;
import com.sztx.pay.center.core.service.MqMessageService;
import com.sztx.pay.center.core.service.OrderMappingService;
import com.sztx.pay.center.core.service.PayCoreCallBack;
import com.sztx.pay.center.core.service.PayCoreService;
import com.sztx.pay.center.core.service.SettleService;
import com.sztx.pay.center.core.service.UserInfoService;
import com.sztx.pay.center.core.service.bean.CallBackInfo;
import com.sztx.pay.center.core.service.bean.PayCoreAccountInfo;
import com.sztx.pay.center.core.service.bean.PayCoreBalancePay;
import com.sztx.pay.center.core.service.bean.PayCoreResult;
import com.sztx.pay.center.core.service.bean.PayCoreTradeInfo;
import com.sztx.pay.center.core.service.bean.TradeInfo;
import com.sztx.pay.center.core.service.util.SettleTradeType;
import com.sztx.pay.center.core.service.util.SettleType;
import com.sztx.pay.center.dataaccess.dao.mysql.OrderB2cMysqlDAO;
import com.sztx.pay.center.dataaccess.dao.redis.LockRedisDAO;
import com.sztx.pay.center.dataaccess.domain.OrderB2cDO;
import com.sztx.pay.center.dataaccess.domain.UserActDO;
import com.sztx.pay.center.dataaccess.domain.UserBindCardDO;
import com.sztx.pay.center.rpc.api.domain.B2CRequest;
import com.sztx.pay.center.rpc.api.domain.TradeBaseRequest;
import com.sztx.pay.center.rpc.api.domain.TradeFlowMessage;
import com.sztx.pay.center.rpc.api.domain.TradeResponse;
import com.sztx.pay.risk.rpc.api.domain.TradeType;
import com.sztx.se.common.exception.BusinessException;
import com.sztx.se.common.util.StringUtil;
import com.sztx.se.rpc.dubbo.client.DubboClientFactory;

public class TradeB2CService extends TradeService implements PayCoreCallBack {

	OrderB2cMysqlDAO orderB2cMysqlDAO;

	AccountService accountService;

	BillnoService billnoService;

	PayCoreService payCoreService;

	@Autowired
	private LockRedisDAO lockRedisDAO;
	@Autowired
	TradeConfirmOrderService confirmOrderService;
	@Autowired
	OrderMappingService orderMappingService;
	@Autowired
	CallBackService callBackService;
	@Autowired
	SettleService settleService;
	@Autowired
	private DubboClientFactory dubboConsumerFactory;
	@Autowired
	private ActService actService;
	@Autowired
	private UserInfoService userInfoService;
	@Autowired
	private MqMessageService mqMessageService;
	@Override
	void checkPrivateParam(Map<String, String> params) {
		
		String payerUserId = params.get("payerUserId");
		String openId = params.get("openId");
		String bindNo = params.get("bindNo");
		String payeeUserId = params.get("payeeUserId");
		String bankId = params.get("bankId");
		String amount = params.get("amount");
		String goodsName = params.get("goodsName");
		String goodsDetail = params.get("goodsDetail");
		String guaranteeType = params.get("guaranteeType");
		// String b2cPayPwd = params.get("b2cPayPwd");
		String channelId = params.get("channelId");
		String businessType = params.get("businessType");
		String productType = params.get("productType");
		String riskParams = params.get("riskParams");
		String returnUrl = params.get("returnUrl");
		String notifyUrl = params.get("notifyUrl");

		ValidateUtil.isNotBlank(payerUserId, "payerUserId不能为空");

		if (StringUtil.isNotBlank(openId)) {
			ValidateUtil.gt(openId.length(), 27, "openId格式不正确");
		}
		if (StringUtil.isNotBlank(bindNo)) {
			ValidateUtil.strEqualLen(bindNo, 8, "bindNo格式不正确");
		}

		ValidateUtil.isNotBlank(payeeUserId, "payeeUserId不能为空");
		ValidateUtil.isNotBlank(bankId, "bankId不能为空");
		ValidateUtil.isNotBlank(amount, "amount不能为空");
		ValidateUtil.isNotBlank(goodsName, "goodsName不能为空");
		ValidateUtil.isNotBlank(channelId, "channelId不能为空");
		ValidateUtil.isNotBlank(businessType, "businessType不能为空");
		ValidateUtil.isNotBlank(productType, "productType不能为空");
		
		if(StringUtil.isBlank(bankId) || !bankId.equals(Constance.BERBON_PAY_BANKID)){
			ValidateUtil.isNotBlank(notifyUrl, "notifyUrl不能为空");
		}
		
		
		// ValidateUtil.isNotBlank(riskParams, "riskParams不能为空");
		if (StringUtil.isBlank(bindNo) && bankId.startsWith("1")) {
			ValidateUtil.isNotBlank(returnUrl, "网银支付,returnUrl不能为空");
		}

		if (StringUtil.isNotBlank(goodsDetail)) {
			ValidateUtil.strMaxLen(goodsDetail, 200, "goodsDetail不能超过200个字符");
		}

		ValidateUtil.isNotBlank(guaranteeType, "guaranteeType不能为空");

		ValidateUtil.isNotBlank(channelId, "channelId不能为空");
		ValidateUtil.isNotBlank(businessType, "businessType不能为空");
		ValidateUtil.isNotBlank(productType, "productType不能为空");
		// ValidateUtil.isNotBlank(riskParams, "riskParams不能为空");

		int productTypeInt = Integer.parseInt(productType);
		ValidateUtil.isBetween(productTypeInt, 1, 2, "productType错误");
		if (StringUtil.isNotBlank(riskParams)) {
			try {
				JSONObject.parseObject(riskParams);
			} catch (Exception e) {
				throw new BusinessException("riskParams参数错误");
			}
		}
	}

	@Override
	boolean isRepeatOrder(Map<String, String> params) {

		String orderId = params.get("orderId");
		String bankId = params.get("bankId");
		boolean lockOrder = lockRedisDAO.lockOrder(orderId, "0", "checkB2cRepeat", 3l);
		if (!lockOrder) throw new BusinessException("支付请求过频繁,请稍后重试!");
		OrderB2cDO b2cOrder = orderB2cMysqlDAO.findByOrderId(orderId);
		if (b2cOrder != null) {
			return true;
		}

		return false;
	}

	@Override
	String recordOrder(TradeBaseRequest request) {

		if (!(request instanceof B2CRequest)) {
			logger.error("请求参数错误request不是B2CRequest对象");
			throw new BusinessException("服务器正忙，请稍后再试");
		}
		B2CRequest b2cRequest = (B2CRequest) request;

		int amount = b2cRequest.getAmount();
		String attach = b2cRequest.getAttach();
		String bankId = b2cRequest.getBankId();
		String bindNo = b2cRequest.getBindNo();
		String expireTime = b2cRequest.getExpireTime();
		String goodsDetail = b2cRequest.getGoodsDetail();
		String goodsName = b2cRequest.getGoodsName();
		int guaranteeType = b2cRequest.getGuaranteeType();
		String notifyUrl = b2cRequest.getNotifyUrl();
		String openId = b2cRequest.getOpenId();
		String orderId = b2cRequest.getOrderId();
		String orderTime = b2cRequest.getOrderTime();
		String payeeUserId = b2cRequest.getPayeeUserId();
		String payerUserId = b2cRequest.getPayerUserId();
		String srcIp = b2cRequest.getSrcIp();
		String returnUrl = b2cRequest.getReturnUrl();
		String srcChannel = b2cRequest.getSrcChannel();
		String isUsePwdStr = b2cRequest.getIsUsePwd();

		String platChannelId = b2cRequest.getChannelId();
		String businessType = b2cRequest.getBusinessType();
		int productType = b2cRequest.getProductType();
		String riskParams = b2cRequest.getRiskParams();
		
		if (!bankId.startsWith("0") && !bankId.startsWith("2")) {
			OrderB2cDO lastOrder = orderB2cMysqlDAO.findOrderByPayParams(orderId, amount, payerUserId, bankId);
			if (lastOrder != null) return lastOrder.getTradeOrderId();
		}
		
		if(bankId.equals(Constance.BERBON_PAY_BANKID)){
			Long actBalance = payerActInfo.getActBalance();
			if(amount > actBalance){
				lockRedisDAO.unlockOrder(orderId, "0", "checkB2cRepeat");
				throw new BusinessException("账户余额不足");
			}
		}
		
		Byte isUsePwd = (isUsePwdStr != null && "1".equals(isUsePwdStr)) ? new Byte("1") : new Byte("2");

		String payerUserAct = payerActInfo.getActNo();

		String payeeUserAct = payeeActInfo.getActNo();// 余额账户

		long calculateHandlingFee = 0l;
		
		CardType cardType = null;
		if(payerBindCardInfo != null && payerBindCardInfo.getCardType() != null){
			cardType = CardType.valueOf(payerBindCardInfo.getCardType());
		}
		if (guaranteeType == GuaranteeType.QUICK.getCode()) {
			calculateHandlingFee = settleService.calculateHandlingFee(SettleTradeType.TRADE, SettleType.NOW, payeeUserId, (long)amount,platChannelId,bankId,cardType);
		} else {
			calculateHandlingFee = settleService.calculateHandlingFee(SettleTradeType.TRADE, SettleType.LATTER, payeeUserId, (long)amount,platChannelId,bankId,cardType);
		}
		logger.info("guaranteeType:" + guaranteeType);
		logger.info("calculateHandlingFee:" + calculateHandlingFee);
		logger.info("amount:" + amount);

		if (amount <= calculateHandlingFee) {
			throw new BusinessException("手续费不能大于、等于交易金额");
		}

		String tradeOrderId = billnoService.nextB2CTradeNo();
		OrderB2cDO orderB2cDO = new OrderB2cDO();
		orderB2cDO.setTradeOrderId(tradeOrderId);
		orderB2cDO.setAttach(attach);
		orderB2cDO.setPayBankId(bankId);
		orderB2cDO.setPayerBindNo(bindNo);
		orderB2cDO.setGoodsDetail(goodsDetail);
		orderB2cDO.setGoodsName(goodsName);
		orderB2cDO.setGuaranteeType(guaranteeType);
		orderB2cDO.setInnerStatus(1);
		orderB2cDO.setNotifyUrl(notifyUrl);
		orderB2cDO.setOrderId(orderId);
		orderB2cDO.setPayAmount(0l);
		orderB2cDO.setAddTime(new Date());
		orderB2cDO.setReturnUrl(returnUrl);
		orderB2cDO.setSourceIp(srcIp);
		orderB2cDO.setTradeAmount((long) amount);
		orderB2cDO.setOrderChannel(Integer.parseInt(srcChannel));
		orderB2cDO.setPayeeUserAct(payeeUserAct);
		orderB2cDO.setPayeeUserId(payeeUserId);
		orderB2cDO.setPayerUserAct(payerUserAct);
		orderB2cDO.setPayerUserId(payerUserId);
		orderB2cDO.setOpenId(openId);
		orderB2cDO.setIsUsePwd(isUsePwd);
		orderB2cDO.setPlatChannelId(platChannelId);
		orderB2cDO.setBusinessType(businessType);
		orderB2cDO.setProductType(productType);
		orderB2cDO.setRiskParams(riskParams);

		orderB2cDO.setOrderTime(DateUtil.parse(orderTime, "yyyyMMddHHmmss"));
		if (expireTime != null) {
			orderB2cDO.setExpireTime(DateUtil.parse(expireTime, "yyyyMMddHHmmss"));
		}

		// orderB2cDO.setChannelType(new Byte("1"));
		// orderB2cDO.setCreateUser("21");
		orderB2cDO.setOrderStatus(Constance.B2COrderState.WAITING_PAY.getCode());
		orderB2cDO.setOrderDesc(Constance.B2COrderState.WAITING_PAY.getDesc());
		// orderB2cDO.setOrderType(new Byte("3"));
		orderB2cDO.setFee((int) calculateHandlingFee);
		orderB2cDO.setPayTime(null);
		orderB2cDO.setPayType(null);
		orderB2cDO.setSureReceiveTime(null);

		orderB2cMysqlDAO.save(orderB2cDO);

		return tradeOrderId;
	}

	@Override
	UserBindCardDO getPayerBindInfo(Map<String, String> params) {
		String bindNo = params.get("bindNo");
		String payerUserId = params.get("payerUserId");
		String bankId = params.get("bankId");
		String channelId = params.get("channelId");
		String clientSourceType = params.get("clientSourceType");
		if (Constance.BERBON_PAY_BANKID.equals(bankId)) {
			return null;
		}
		
		UserBindCardDO userBindCardDO = accountService.findUserBindInfo(bindNo, payerUserId, BindCardType.BIND_QUICK_PAY);
		
		if (userBindCardDO == null ) throw new BusinessException("未查询到绑定号【"+ bindNo +"】相关信息" );
		//支持使用信用卡:clientSourceType为1,3或者缴费渠道
		if(userBindCardDO.getCardType() == Constance.CardType.CARD_CREDIT.getValue()) {
//			if (!JFUtils.isJFChannel(channelId) && !checkclientSourceType(clientSourceType)) {
//				throw new BusinessException("暂不支持使用信用卡支付");
//			}
			if (!JFUtils.isJFChannel(channelId)) {
				throw new BusinessException("暂不支持使用信用卡支付");
			}
		}
		
		return userBindCardDO;
	}

	@Override
	UserBindCardDO getPayeeBindInfo(Map<String, String> params) {

		return null;
	}

	@Override
	TradeResponse invokePayCore(Map<String, String> params) {
		TradeInfo tradeInfo = new TradeInfo();

		int amount = Integer.parseInt(params.get("amount"));
		String goodsDetail = params.get("goodsDetail");
		String goodsName = params.get("goodsName");
		String notifyUrl = params.get("notifyUrl");
		String b2cOrderId = params.get("tradeOrderId");
		Integer referOrderType = Constance.TradeOrderType.B2C_TRADE_ORDER.getCode();
		String remark = params.get("remark");
		String returnUrl = params.get("returnUrl");
		String openId = params.get("openId");
		String bankId = params.get("bankId");
		String bindNo = params.get("bindNo");
		String attach = params.get("attach");
		String businessType = params.get("businessType");
		String authCode = params.get("authCode");
		String gateWayChannelId = params.get("gateWayChannelId");
		String routeNo = params.get("routeNo");

		OrderB2cDO findById = orderB2cMysqlDAO.findById(b2cOrderId);
		
		if (findById.getOrderStatus() == Constance.B2COrderState.PAYING.getCode()) {
			String payParams = findById.getPayParams();
			PayCoreResult result = JSONObject.parseObject(payParams, PayCoreResult.class);
			
			TradeResponse resonse = new TradeResponse();
			resonse.setPayUrl(result.getPayUrl());
			resonse.setTradeOrderId(b2cOrderId);
			resonse.setResultCode(String.valueOf(result.getTradeSataus()));
			resonse.setResultMsg(result.getTradeDesc());
			resonse.setPayParams(result.getPayParams());

			return resonse;
		}
		if (!StringUtil.isBlank(returnUrl)) {
			returnUrl = ConfigUtil.innerReturnUrl;// 将回调地址转换
		}
		// 初始状态设置为成功,兼容余额支付没有第一步充值
		PayCoreResult result = new PayCoreResult();
		String resultStr = null;
		result.setTradeSataus(PayFlowState.SUCCESS.getCode());
		result.setTradeDesc(PayFlowState.SUCCESS.getDesc());
		result.setChannelId(Constance.CHANNEL_ID_SZTX);
		// 如果不是余额支付进行第一步:充值
		if (!Constance.BERBON_PAY_BANKID.equals(bankId)) {
			String payMappingOrderId = orderMappingService.addMappingOrder(b2cOrderId, (byte) PayFlowType.PAY.getCode());

			tradeInfo.setAmount(amount);
			tradeInfo.setGoodsDetail(goodsDetail);
			tradeInfo.setGoodsName(goodsName);
			tradeInfo.setNotifyUrl(notifyUrl);
			tradeInfo.setReturnUrl(returnUrl);
			tradeInfo.setRemark("B2C交易充值用户余额");
			tradeInfo.setBankId(bankId);
			tradeInfo.setOrderType(Constance.TradeOrderType.B2C_TRADE_ORDER);
			tradeInfo.setOriginOrderNo(b2cOrderId);
			// 此处传入映射订单号
			tradeInfo.setTradeOrderId(payMappingOrderId);
			tradeInfo.setBusinessType(businessType);
			tradeInfo.setAuthCode(authCode);
			tradeInfo.setGateWayChannelId(gateWayChannelId);
			//tradeInfo.setRouteNo(routeNo);
			
			PayCoreAccountInfo payerAccount = new PayCoreAccountInfo();

			payerAccount.setPayerUserId(payerActInfo.getUserId());
			payerAccount.setPayerUserType(payerActInfo.getUserType());
			payerAccount.setPayerActType(UserActType.valueOf(payerActInfo.getActType()));
			payerAccount.setPayerActNo(payerActInfo.getActNo());
			// payerAccount.setActNo(payerActInfo.getActNo());

			if (payerBindCardInfo != null) {
				payerAccount.setBankAct(payerBindCardInfo.getCardNo());
				payerAccount.setBankId(payerBindCardInfo.getBankId());
				payerAccount.setCardType(CardType.valueOf(payerBindCardInfo.getCardType()));
				payerAccount.setIdentityType(IdCardType.valueOf(payerBindCardInfo.getIdentityType()));
				payerAccount.setIdentityNo(payerBindCardInfo.getIdentityNo());
				payerAccount.setMobile(payerBindCardInfo.getMobileNo());
				payerAccount.setRealName(payerBindCardInfo.getRealName());
				payerAccount.setBankName(payerBindCardInfo.getBankName());
				payerAccount.setCardActType(CardActType.valueOf(payerBindCardInfo.getCardActType()));

				if (CardType.CARD_CREDIT.getValue() == payerBindCardInfo.getCardType()) {
					payerAccount.setBankActCvv(payerBindCardInfo.getCardCvv());
					payerAccount.setBankActExpire(payerBindCardInfo.getExpireDate());
				}
			}

			payerAccount.setOpenId(openId);

			if(JFUtils.isJFChannel(findById.getPlatChannelId()) && StringUtil.isBlank(routeNo)){
				String jfRouteNo = JFUtils.getJfDefaultRouteNo(1);
				tradeInfo.setRouteNo(jfRouteNo);
			}else if(StringUtil.isNotBlank(routeNo)){
				tradeInfo.setRouteNo(routeNo);
			}
			
			// 将第一步充值结果赋值给result
			result = payCoreService.pay(payerAccount, tradeInfo, "tradeB2CService");
			resultStr = JSONObject.toJSONString(result);
		}

		if ((PayFlowState.SUCCESS.getCode() == result.getTradeSataus())) {

			String balanceTradeMappingOrderId = orderMappingService.addMappingOrder(b2cOrderId, (byte) PayFlowType.BALANCE_TRADE.getCode());

			PayCoreBalancePay balancePay = new PayCoreBalancePay();
			balancePay.setAmount(amount);
			balancePay.setAttach(attach);
//			balancePay.setFeeAmount(0);
			balancePay.setOrderId(balanceTradeMappingOrderId);
			balancePay.setOriginOrderId(b2cOrderId);
			balancePay.setPayeeActNo(payeeActInfo.getActNo());
			balancePay.setPayeeActType(UserActType.valueOf(payeeActInfo.getActType()));
			balancePay.setPayeeUserId(payeeActInfo.getUserId());
			balancePay.setPayeeUserType(payeeActInfo.getUserType());
			balancePay.setPayerActNo(payerActInfo.getActNo());
			balancePay.setPayerActType(UserActType.valueOf(payerActInfo.getActType()));
			balancePay.setPayerUserId(payerActInfo.getUserId());
			balancePay.setPayerUserType(payerActInfo.getUserType());
			balancePay.setTradeOrderType(TradeOrderType.B2C_TRADE_ORDER);
			balancePay.setBusinessType(businessType);
			// TODO 成功进行充值后,使用余额支付给商家,后续处理未完成
			try {
				payCoreService.balancePay(balancePay);
			} catch (BusinessException e) {
				// TODO 业务异常处理
				logger.info("", e);
				result.setTradeSataus(PayFlowState.FAIL.getCode());
				result.setTradeDesc(e.getMessage());
			} catch (Exception e) {
				logger.info("", e);
				// TODO 未知异常处理
				result.setTradeSataus(PayFlowState.EXCEPTION.getCode());
				result.setTradeDesc("未知异常!");
			}
//			resultStr = null;
		}

		callBack(b2cOrderId, result.getTradeSataus(), amount, bankId, attach, result.getTradeDesc(), resultStr,result.getChannelId());

		TradeResponse resonse = new TradeResponse();
		resonse.setPayUrl(result.getPayUrl());
		resonse.setTradeOrderId(b2cOrderId);
		resonse.setResultCode(String.valueOf(result.getTradeSataus()));
		resonse.setResultMsg(result.getTradeDesc());
		resonse.setPayParams(result.getPayParams());
		resonse.setCodeImgUrl(result.getCodeImgUrl());

		return resonse;

	}

	@Override
	void handerPayCoreResult() {

	}

	@Override
	UserActDO getPayerActInfo(TradeBaseRequest request) {
		if (!(request instanceof B2CRequest)) {
			logger.error("请求参数错误request不是B2CRequest对象");
			throw new BusinessException("服务器正忙，请稍后再试");
		}
		B2CRequest b2cRequest = (B2CRequest) request;

		String userId = b2cRequest.getPayerUserId();
		String channelId = b2cRequest.getChannelId();
		
		UserActType userActType = UserActType.CASH;
		if (JFUtils.isJFChannel(channelId)) {
			userActType = UserActType.JF;
		}

		return actService.findValidActInfo(userId, userActType, true);
	}

	@Override
	UserActDO getPayeeActInfo(TradeBaseRequest request) {
		if (!(request instanceof B2CRequest)) {
			logger.error("请求参数错误request不是B2CRequest对象");
			throw new BusinessException("服务器正忙，请稍后再试");
		}
		B2CRequest b2cRequest = (B2CRequest) request;
		String payeeUserId = b2cRequest.getPayeeUserId();

		return actService.findValidActInfo(payeeUserId, UserActType.TRADE, false);
	}

	public void setOrderB2cMysqlDAO(OrderB2cMysqlDAO orderB2cMysqlDAO) {
		this.orderB2cMysqlDAO = orderB2cMysqlDAO;
	}

	public void setAccountService(AccountService accountService) {
		this.accountService = accountService;
	}

	public void setBillnoService(BillnoService billnoService) {
		this.billnoService = billnoService;
	}

	public void setPayCoreService(PayCoreService payCoreService) {
		this.payCoreService = payCoreService;
	}

	@Override
	@Async
	public void callPayResult(PayCoreTradeInfo tradeInfo) {
		logger.info("支付中心回调：" + tradeInfo);

		String mappingOrderId = tradeInfo.getReferOrderId();

		String tradeOrderId = orderMappingService.getTradeOrderId(mappingOrderId);


		OrderB2cDO b2cOrder = orderB2cMysqlDAO.findById(tradeOrderId);
		
		if (b2cOrder == null) {
			logger.error("未找到b2c交易订单->" + tradeOrderId);
			return;
		}
		
		String businessType = b2cOrder.getBusinessType();
		int oldOrderStatus = b2cOrder.getOrderStatus();

		// 只处理订单状态为待支付和支付中
		if (oldOrderStatus != B2COrderState.WAITING_PAY.getCode() && oldOrderStatus != B2COrderState.PAYING.getCode()) {
			logger.error("callPayResult订单状态不为待支付，不做处理" + b2cOrder);
			return;
		}
		
		int tradeStatus = tradeInfo.getPayFlowState().getCode();
		String desc = null;
		
		if (tradeInfo.getPayFlowState() == PayFlowState.SUCCESS) {
			
			String balanceTradeMappingOrderId = orderMappingService.addMappingOrder(tradeOrderId, (byte) PayFlowType.BALANCE_TRADE.getCode());

			PayCoreBalancePay balancePay = new PayCoreBalancePay();
			balancePay.setAmount(b2cOrder.getTradeAmount());
			balancePay.setAttach(b2cOrder.getAttach());
//			balancePay.setFeeAmount(0);
			balancePay.setOrderId(balanceTradeMappingOrderId);
			balancePay.setOriginOrderId(tradeOrderId);
			
			B2CRequest request = new B2CRequest();
			request.setPayeeUserId(b2cOrder.getPayeeUserId());
			request.setPayerUserId(b2cOrder.getPayerUserId());
			request.setChannelId(b2cOrder.getPlatChannelId());
			
			UserActDO payeeActInfo2 = getPayeeActInfo(request);
			balancePay.setPayeeActNo(payeeActInfo2.getActNo());
			balancePay.setPayeeActType(UserActType.valueOf(payeeActInfo2.getActType()));
			balancePay.setPayeeUserId(payeeActInfo2.getUserId());
			balancePay.setPayeeUserType(payeeActInfo2.getUserType());
			
			UserActDO payerActInfo2 =  getPayerActInfo(request);
			balancePay.setPayerActNo(payerActInfo2.getActNo());
			balancePay.setPayerActType(UserActType.valueOf(payerActInfo2.getActType()));
			balancePay.setPayerUserId(payerActInfo2.getUserId());
			balancePay.setPayerUserType(payerActInfo2.getUserType());
			balancePay.setTradeOrderType(TradeOrderType.B2C_TRADE_ORDER);
			balancePay.setBusinessType(businessType);
			
			try {
				payCoreService.balancePay(balancePay);
			} catch (BusinessException e) {
				logger.info("", e);
				// TODO 业务异常处理
				tradeStatus = PayFlowState.FAIL.getCode();
				desc = e.getMessage();
			} catch (Exception e) {
				logger.info("", e);
				// TODO 未知异常处理
				tradeStatus = PayFlowState.EXCEPTION.getCode();
				desc = "未知异常";
			}
		}

		callBack(tradeOrderId, tradeStatus, (long) tradeInfo.getAmount(), b2cOrder.getPayBankId(), b2cOrder.getAttach(), desc, null, tradeInfo.getChannelId());

	}

	// 通知业务系统
	@Async
	private void callBack(String tradeOrderId, int state, long payAmount, String bankId, String attach, String desc, String resultStr, String channlId) {
		
		OrderB2cDO b2cOrder = orderB2cMysqlDAO.findById(tradeOrderId);
		if (b2cOrder == null) {
			logger.error("未找到b2c交易订单->" + tradeOrderId);
			return;
		}

		int oldOrderStatus = b2cOrder.getOrderStatus();

		// 只处理订单状态为待支付和支付中
		if (oldOrderStatus != B2COrderState.WAITING_PAY.getCode() && oldOrderStatus != B2COrderState.PAYING.getCode()) {
			logger.error("callBack订单状态不为待支付，不做处理" + b2cOrder);
			return;
		}

		// 结算类别
		int guaranteeType = b2cOrder.getGuaranteeType();

		Date mDate = new Date();

		OrderB2cDO updateOrder = new OrderB2cDO();
		updateOrder.setTradeOrderId(tradeOrderId);

		PayFlowState newOrderStatus = PayFlowState.valueOf(state);

		Long amount = b2cOrder.getTradeAmount();
		String payerUserId = b2cOrder.getPayerUserId();
		CallBackOrderState callBackOrderState = null;

		switch (newOrderStatus) {
		case SUCCESS:

			updateOrder.setPayAmount(payAmount);
			updateOrder.setPayTime(mDate);
			updateOrder.setOrderStatus(B2COrderState.SUCCESS.getCode());
			updateOrder.setOrderDesc(B2COrderState.SUCCESS.getDesc());

			callBackOrderState = CallBackOrderState.SUCCESS;
			boolean flag = lockRedisDAO.lockOrder(tradeOrderId + "ZJLS", "success");
			if (flag) {
				boolean isNoUsePwd = (int) b2cOrder.getIsUsePwd() == 1 ? true : false;
				// riskControlService.updateUserRiskData(b2cOrder.getPayerUserId()
				// , TranType.PURCHASE,b2cOrder.getTradeAmount(),isNoUsePwd);

				int productType = b2cOrder.getProductType();
				TradeType tradeType = null;
				if (productType == 1) {
					tradeType = TradeType.PURCHASE_ENTITY;
				} else if (productType == 2) {
					tradeType = TradeType.PURCHASE_VIRTUAL;
				}
				logger.info("b2c成功调用风控:" + tradeOrderId);
				this.newupdateRisk(tradeType, b2cOrder.getOrderId(), b2cOrder.getPlatChannelId(), b2cOrder.getBusinessType(), productType, b2cOrder.getPayerUserId(), b2cOrder.getPayeeUserId(),
						(int) payAmount, String.valueOf(b2cOrder.getOrderChannel()), b2cOrder.getSourceIp(), b2cOrder.getRiskParams(), isNoUsePwd, b2cOrder.getAddTime());
				try {
					TradeFlowMessage message = new TradeFlowMessage();
					message.setTradeType(TradeMessageType.B2C.getCode());
					message.setBerbonAcc(b2cOrder.getPayerUserId());
					message.setBusinessType(b2cOrder.getBusinessType());
					message.setTradeAmount(b2cOrder.getTradeAmount());
					message.setReceiveAmount(b2cOrder.getTradeAmount());
					message.setOtherBerbonAcc(b2cOrder.getPayeeUserId());
					message.setPayOrderNo(tradeOrderId);
					message.setTradeOrderNo(b2cOrder.getOrderId());
					message.setPayType(getpayTypeByBankId(bankId, payerUserId, b2cOrder.getPayerBindNo()));
					logger.info("mq通知trade-center:" + message);
					sendTradeFlowMessage(message);
					logger.info("mq通知trade-center结束:" + tradeOrderId);
				} catch (Exception e) {
					logger.info("mq通知trade-center失败:",e);
				}
			}
			break;
		case FAIL:
			updateOrder.setOrderStatus(B2COrderState.FAIL.getCode());
			updateOrder.setOrderDesc(desc);
			callBackOrderState = CallBackOrderState.FAIL;
			break;
		case EXCEPTION:
			updateOrder.setOrderStatus(B2COrderState.EXCEPTION.getCode());
			updateOrder.setOrderDesc(desc);
			callBackOrderState = CallBackOrderState.EXCEPTION;
			break;
		case PAYING:
			updateOrder.setOrderStatus(B2COrderState.PAYING.getCode());
			updateOrder.setOrderDesc(B2COrderState.PAYING.getDesc());
			break;
		default:
			return;
		}

		updateOrder.setUpdateTime(mDate);

		// 1.更改订单状态
		logger.info("updateOrder:订单状态" + updateOrder.getOrderStatus());
		if (resultStr != null) updateOrder.setPayParams(resultStr);
		updateOrder.setPayChannelId(channlId);
		
		
		//未传描述字段 使用枚举描述进行更新
		if(updateOrder.getOrderStatus() != null && updateOrder.getOrderDesc() == null){
			B2COrderState orderState = B2COrderState.valueOf(updateOrder.getOrderStatus());
			updateOrder.setOrderDesc(orderState.getDesc());
		}
		
		orderB2cMysqlDAO.updateInfo(updateOrder);
		
		lockRedisDAO.unlockOrder(b2cOrder.getOrderId(), "0", "checkB2cRepeat");

		if (newOrderStatus == PayFlowState.SUCCESS && guaranteeType == GuaranteeType.QUICK.getCode()) { // 自动确认收货
			confirmOrderService.asyncComfirmOrder(tradeOrderId, null, null, true, b2cOrder.getOrderId());
		}
		// 2.记录用户账户资金流水

		// 3.通知回调系统
		if (callBackOrderState != null) {
			CallBackInfo callBackInfo = new CallBackInfo();
			callBackInfo.setTradeOrderId(b2cOrder.getTradeOrderId());
			callBackInfo.setOutOrderId(b2cOrder.getOrderId());
			callBackInfo.setNotfiyUrl(b2cOrder.getNotifyUrl());
			callBackInfo.setReturnUrl(b2cOrder.getReturnUrl());
			callBackInfo.setTotalFee(b2cOrder.getFee());
			callBackInfo.setPayAmount((int) payAmount);
			callBackInfo.setAttach(desc);
			callBackInfo.setPayTime(mDate);
			callBackInfo.setTradeCrateTime(b2cOrder.getAddTime());
			callBackInfo.setOrderType(TradeOrderType.B2C_TRADE_ORDER);
			callBackInfo.setOrderState(callBackOrderState);
			callBackService.callBack(callBackInfo);
		}

	}
	private boolean sendTradeFlowMessage(TradeFlowMessage message) {
		String json = JSONObject.toJSONString(message);
		mqMessageService.sendTradeFlowMsg(json);
		return true;
	}
	
	private String getpayTypeByBankId(String bankId, String payerUserId, String bindNo){
		if(bankId.startsWith("0"))
			return "倍棒余额";
		else if(bankId.startsWith("1"))
			return "网银支付";
		else if(bankId.startsWith("2")){
			UserBindCardDO userBindCardDO = accountService.findUserBindInfoIgnoreState(bindNo, payerUserId, BindCardType.BIND_QUICK_PAY);
			String cardNo = YHBFSensitiveEnc.sensitiveDec(userBindCardDO.getCardNo(), "cardno");
			cardNo = cardNo.substring(cardNo.length() - 4, cardNo.length());
			String payType = userBindCardDO.getBankName() + "(" + cardNo + ")";
			return payType;
		}else if(bankId.startsWith("3")){
			if(("3000000").equals(bankId))
				return "支付宝WAP支付";
			else if(("3000001").equals(bankId))
				return "微信公众号支付";
			else if(("3000002").equals(bankId))
				return "微信APP支付";
			else  if(("3000003").equals(bankId))
				return "微信APP支付";
			else  if(("3000004").equals(bankId))
				return "威富通支付宝扫码支付";
			else  if(("3000005").equals(bankId))
				return "威富通微信扫码支付";
		}
		return null;
	}

	private boolean checkclientSourceType(String clientSourceType) {
		if (StringUtils.isBlank(clientSourceType)) {
			return false;	
		}
		if (Integer.parseInt(clientSourceType) == 1 || Integer.parseInt(clientSourceType) == 3) {
			return true;
		}
		return false;
	}
	
}
